package com.gcb.aop;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @description controller层日志切面
 * @create 2020-04-07 10:02
 */
@Aspect
@Component
@Slf4j
public class ControllerLogAspect {

    /**
     * 定义切点
     */
    @Pointcut("execution(* com.gcb.controller..*(..))")
    public void point() {
    }

    @Around("point()")
    @SneakyThrows
    public Object doAround(ProceedingJoinPoint pjp) {
        // 请求线程id
        String threadId = Thread.currentThread().getName();
        //记录请求开始执行时间：
        long beginTime = System.currentTimeMillis();
        //获取请求信息
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert sra != null;
        HttpServletRequest request = sra.getRequest();

        // 请求地址
        String requestURI = request.getRequestURI();
        // 获取类名
        String clazzName = pjp.getTarget().getClass().getSimpleName();
        // 获取方法名
        String methodName = pjp.getSignature().getName();
        // 获取请求方式
        String method = request.getMethod() + " || " + request.getContentType();

        // 获取请求参数：
        String parameterValues = null;
        if ("POST".equals(request.getMethod()) && request.getContentType().startsWith("application/json")) {
            // 获取json参数
            Object requestBody = pjp.getArgs()[0];
            if(requestBody != null){
                parameterValues = JSONUtil.toJsonStr(requestBody);
            }
        } else {
            parameterValues = JSONUtil.toJsonStr(getParameters(request.getParameterNames(), request));
        }
        // 打印日志
        log.info("\n==========threadId：{} 请求开始：==========\n" +
                        "请求地址：{}，\n" +
                        "请求方式：{}，\n" +
                        "请求类名：{}，\n" +
                        "请求方法名：{}，\n" +
                        "请求参数：{}",
                threadId, requestURI, clazzName, methodName, method, parameterValues);

        Object result = pjp.proceed();
        // 请求结果
        String resultStr = JSON.toJSONString(result);

        //记录请求完成执行时间：
        long endTime = System.currentTimeMillis();
        long usedTime = endTime - beginTime;
        log.info("\n==========threadId：{} 请求结束：==========\n" +
                        "请求地址：{}，\n" +
                        "请求结果：{}，\n" +
                        "请求耗时：{} ms",
                threadId, requestURI, resultStr, usedTime);

        return result;
    }

    private Map<String, Object> getParameters(Enumeration<String> headerNames, HttpServletRequest request) {
        Map<String, Object> parameterNameAndValues = new HashMap<>();
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            String value = request.getParameter(key);
            parameterNameAndValues.put(key, value);
        }
        return parameterNameAndValues;
    }
}
